home *** CD-ROM | disk | FTP | other *** search
/ Chip 2001 June / CHIP Haziran 2001.iso / prog / haziran / 19 / setup.exe / data.z / gt64_lib.c < prev    next >
C/C++ Source or Header  |  2001-04-11  |  19KB  |  611 lines

  1. ////////////////////////////////////////////////////////////////
  2. // File - GT64_LIB.C
  3. //
  4. // Library for 'WinDriver for Galileo GT64' API. 
  5. // The basic idea is to get a handle for the board
  6. // with GT64_Open() and use it in the rest of the program
  7. // when calling WD functions.  Call GT64_Close() when done.
  8. // 
  9. ////////////////////////////////////////////////////////////////
  10.  
  11. #include "../../../include/windrvr.h"
  12. #include "../../../include/windrvr_int_thread.h"
  13. #include "gt64_lib.h"
  14. #include <stdio.h>
  15.  
  16. // this string is set to an error message, if one occurs
  17. CHAR GT64_ErrorString[1024];
  18.  
  19. // internal function used by GT64_Open()
  20. BOOL GT64_DetectCardElements(GT64_HANDLE hGT);
  21.  
  22. DWORD GT64_CountCards (DWORD dwVendorID, DWORD dwDeviceID)
  23. {
  24.     WD_VERSION ver;
  25.     WD_PCI_SCAN_CARDS pciScan;
  26.     HANDLE hWD = INVALID_HANDLE_VALUE;
  27.  
  28.     GT64_ErrorString[0] = '\0';
  29.     hWD = WD_Open();
  30.     // check if handle valid & version OK
  31.     if (hWD==INVALID_HANDLE_VALUE) 
  32.     {
  33.         sprintf( GT64_ErrorString, "Failed opening " WD_PROD_NAME " device\n");
  34.         return 0;
  35.     }
  36.  
  37.     BZERO(ver);
  38.     WD_Version(hWD,&ver);
  39.     if (ver.dwVer<WD_VER) 
  40.     {
  41.         sprintf( GT64_ErrorString, "Incorrect " WD_PROD_NAME " version\n");
  42.         WD_Close (hWD);
  43.         return 0;
  44.     }
  45.  
  46.     BZERO(pciScan);
  47.     pciScan.searchId.dwVendorId = dwVendorID;
  48.     pciScan.searchId.dwDeviceId = dwDeviceID;
  49.     WD_PciScanCards (hWD, &pciScan);
  50.     WD_Close (hWD);
  51.     if (pciScan.dwCards==0)
  52.         sprintf( GT64_ErrorString, "no cards found\n");
  53.     return pciScan.dwCards;
  54. }
  55.  
  56.  
  57. BOOL GT64_Open (GT64_HANDLE *phGT, GT64_VERSION gt64Ver, DWORD dwVendorID, DWORD dwDeviceID, DWORD nCardNum, DWORD dwOptions)
  58. {
  59.     GT64_HANDLE hGT = (GT64_HANDLE) malloc (sizeof (GT64_STRUCT));
  60.  
  61.     WD_VERSION ver;
  62.     WD_PCI_SCAN_CARDS pciScan;
  63.     WD_PCI_CARD_INFO pciCardInfo;
  64.  
  65.     *phGT = NULL;
  66.     GT64_ErrorString[0] = '\0';
  67.     BZERO(*hGT);
  68.  
  69.     hGT->hWD = WD_Open();
  70.  
  71.     // check if handle valid & version OK
  72.     if (hGT->hWD==INVALID_HANDLE_VALUE) 
  73.     {
  74.         sprintf( GT64_ErrorString, "Failed opening " WD_PROD_NAME " device\n");
  75.         goto Exit;
  76.     }
  77.  
  78.     BZERO(ver);
  79.     WD_Version(hGT->hWD,&ver);
  80.     if (ver.dwVer<WD_VER) 
  81.     {
  82.         sprintf( GT64_ErrorString, "Incorrect " WD_PROD_NAME " version\n");
  83.         goto Exit;
  84.     }
  85.     hGT->gt64Ver = gt64Ver;
  86.     BZERO(pciScan);
  87.     pciScan.searchId.dwVendorId = dwVendorID;
  88.     pciScan.searchId.dwDeviceId = dwDeviceID;
  89.     WD_PciScanCards (hGT->hWD, &pciScan);
  90.     if (pciScan.dwCards==0) // Found at least one card
  91.     {
  92.         sprintf( GT64_ErrorString, "Could not find PCI card\n");
  93.         goto Exit;
  94.     }
  95.     if (pciScan.dwCards<=nCardNum)
  96.     {
  97.         sprintf( GT64_ErrorString, "Card out of range of available cards\n");
  98.         goto Exit;
  99.     }
  100.  
  101.     BZERO(pciCardInfo);
  102.     pciCardInfo.pciSlot = pciScan.cardSlot[nCardNum];
  103.     WD_PciGetCardInfo (hGT->hWD, &pciCardInfo);
  104.     hGT->pciSlot = pciCardInfo.pciSlot;
  105.     hGT->cardReg.Card = pciCardInfo.Card;
  106.  
  107.     hGT->fUseInt = (dwOptions & GT64_OPEN_USE_INT) ? TRUE : FALSE;
  108.     if (!hGT->fUseInt)
  109.     {
  110.         DWORD i;
  111.         // Remove interrupt item if not needed
  112.         for (i=0; i<hGT->cardReg.Card.dwItems; i++)
  113.         {
  114.             WD_ITEMS *pItem = &hGT->cardReg.Card.Item[i];
  115.             if (pItem->item==ITEM_INTERRUPT)
  116.                 pItem->item = ITEM_NONE;
  117.         }
  118.     }
  119.     else
  120.     {
  121.         DWORD i;
  122.         // make interrupt resource sharable
  123.         for (i=0; i<hGT->cardReg.Card.dwItems; i++)
  124.         {
  125.             WD_ITEMS *pItem = &hGT->cardReg.Card.Item[i];
  126.             if (pItem->item==ITEM_INTERRUPT)
  127.                 pItem->fNotSharable = FALSE;
  128.         }
  129.     }
  130.  
  131.     hGT->cardReg.fCheckLockOnly = FALSE;
  132.     WD_CardRegister (hGT->hWD, &hGT->cardReg);
  133.     if (hGT->cardReg.hCard==0)
  134.     {
  135.         sprintf ( GT64_ErrorString, "Failed locking device\n");
  136.         goto Exit;
  137.     }
  138.  
  139.     if (!GT64_DetectCardElements(hGT))
  140.     {
  141.         sprintf ( GT64_ErrorString, "Card does not have all items expected for Galileo GT64\n");
  142.         goto Exit;
  143.     }
  144.  
  145.     // Open finished OK
  146.     *phGT = hGT;
  147.     return TRUE;
  148.  
  149. Exit:
  150.     // Error durin Open
  151.     if (hGT->cardReg.hCard) 
  152.         WD_CardUnregister(hGT->hWD, &hGT->cardReg);
  153.     if (hGT->hWD!=INVALID_HANDLE_VALUE)
  154.         WD_Close(hGT->hWD);
  155.     free (hGT);
  156.     return FALSE;
  157. }
  158.  
  159. DWORD GT64_ReadPCIReg(GT64_HANDLE hGT, DWORD dwReg)
  160. {
  161.     WD_PCI_CONFIG_DUMP pciCnf;
  162.     DWORD dwVal;
  163.  
  164.     BZERO (pciCnf);
  165.     pciCnf.pciSlot = hGT->pciSlot;
  166.     pciCnf.pBuffer = &dwVal;
  167.     pciCnf.dwOffset = dwReg;
  168.     pciCnf.dwBytes = 4;
  169.     pciCnf.fIsRead = TRUE;
  170.     WD_PciConfigDump(hGT->hWD,&pciCnf);
  171.     return dwVal;
  172. }
  173.  
  174. void GT64_WritePCIReg(GT64_HANDLE hGT, DWORD dwReg, DWORD dwData)
  175. {
  176.     WD_PCI_CONFIG_DUMP pciCnf;
  177.  
  178.     BZERO (pciCnf);
  179.     pciCnf.pciSlot = hGT->pciSlot;
  180.     pciCnf.pBuffer = &dwData;
  181.     pciCnf.dwOffset = dwReg;
  182.     pciCnf.dwBytes = 4;
  183.     pciCnf.fIsRead = FALSE;
  184.     WD_PciConfigDump(hGT->hWD,&pciCnf);
  185. }
  186.  
  187. BOOL GT64_DetectCardElements(GT64_HANDLE hGT)
  188. {
  189.     DWORD i;
  190.     DWORD ad_sp;
  191.  
  192.     BZERO(hGT->Int);
  193.     BZERO(hGT->addrDesc);
  194.  
  195.     for (i=0; i<hGT->cardReg.Card.dwItems; i++)
  196.     {
  197.         WD_ITEMS *pItem = &hGT->cardReg.Card.Item[i];
  198.  
  199.         switch (pItem->item)
  200.         {
  201.         case ITEM_MEMORY:
  202.         case ITEM_IO:
  203.             {
  204.                 DWORD dwBytes;
  205.                 DWORD dwAddr;
  206.                 DWORD dwPhysAddr;
  207.                 DWORD dwAddrDirect = 0;
  208.                 BOOL fIsMemory;
  209.                 if (pItem->item==ITEM_MEMORY)
  210.                 {
  211.                     dwBytes = pItem->I.Mem.dwBytes;
  212.                     dwAddr = pItem->I.Mem.dwTransAddr;
  213.                     dwAddrDirect = pItem->I.Mem.dwUserDirectAddr;
  214.                     dwPhysAddr = pItem->I.Mem.dwPhysicalAddr;
  215.                     fIsMemory = TRUE;
  216.                 }
  217.                 else 
  218.                 {
  219.                     dwBytes = pItem->I.IO.dwBytes;
  220.                     dwAddr = pItem->I.IO.dwAddr;
  221.                     dwPhysAddr = dwAddr & 0xffff;
  222.                     fIsMemory = FALSE;
  223.                 }
  224.  
  225.                 for (ad_sp=GT64_ADDR_BAR0; ad_sp<=GT64_ADDR_BAR5; ad_sp++)
  226.                 {
  227.                     DWORD dwPCIAddr;
  228.                     DWORD dwPCIReg;
  229.  
  230.                     if (hGT->addrDesc[ad_sp].dwAddr) continue;
  231.                     else if (ad_sp<GT64_ADDR_BAR5) 
  232.                         dwPCIReg = PCI_BAR0 + 4*(ad_sp-GT64_ADDR_BAR0);
  233.                     else dwPCIReg = PCI_ERBAR;
  234.                     dwPCIAddr = GT64_ReadPCIReg(hGT, dwPCIReg);
  235.                     if (dwPCIAddr & 1)
  236.                     {
  237.                         if (fIsMemory) continue;
  238.                         dwPCIAddr &= ~0x3;
  239.                     }
  240.                     else
  241.                     {
  242.                         if (!fIsMemory) continue;
  243.                         dwPCIAddr &= ~0xf;
  244.                     }
  245.                     if (dwPCIAddr==dwPhysAddr)
  246.                         break;
  247.                 }
  248.                 if (ad_sp<=GT64_ADDR_BAR5)
  249.                 {
  250.                     DWORD j;
  251.                     hGT->addrDesc[ad_sp].dwBytes = dwBytes;
  252.                     hGT->addrDesc[ad_sp].dwAddr = dwAddr;
  253.                     hGT->addrDesc[ad_sp].dwAddrDirect = dwAddrDirect;
  254.                     hGT->addrDesc[ad_sp].fIsMemory = fIsMemory;
  255.                     hGT->addrDesc[ad_sp].dwMask = 0;
  256.                     for (j=1; j<hGT->addrDesc[ad_sp].dwBytes && j!=0x80000000; j *= 2)
  257.                     {
  258.                         hGT->addrDesc[ad_sp].dwMask = 
  259.                             (hGT->addrDesc[ad_sp].dwMask << 1) | 1;
  260.                     }
  261.                 }
  262.             }
  263.             break;
  264.         case ITEM_INTERRUPT:
  265.             if (hGT->Int.Int.hInterrupt) return FALSE;
  266.             hGT->Int.Int.hInterrupt = pItem->I.Int.hInterrupt;
  267.             break;
  268.         }
  269.     }
  270.  
  271.     // check that all the items needed were found
  272.     // check if interrupt found
  273.     if (hGT->fUseInt && !hGT->Int.Int.hInterrupt) 
  274.     {
  275.         return FALSE;
  276.     }
  277.  
  278.     // check that the registers space was found
  279.     if (!GT64_IsAddrSpaceActive(hGT, GT64_ADDR_REG)) 
  280.             //|| hGT->addrDesc[GT64_ADDR_REG].dwBytes!=GT64_RANGE_REG)
  281.         return FALSE;
  282.  
  283.     // check that address space 0 was found
  284.     if (!GT64_IsAddrSpaceActive(hGT, GT64_ADDR_BAR0)) return FALSE;
  285.  
  286.     return TRUE;
  287. }
  288.  
  289. void GT64_Close(GT64_HANDLE hGT)
  290. {
  291.     // disable interrupts
  292.     if (GT64_IntIsEnabled(hGT))
  293.         GT64_IntDisable(hGT);
  294.  
  295.     // unregister card
  296.     if (hGT->cardReg.hCard) 
  297.         WD_CardUnregister(hGT->hWD, &hGT->cardReg);
  298.  
  299.     // close WinDriver
  300.     WD_Close(hGT->hWD);
  301.  
  302.     free (hGT);
  303. }
  304.  
  305. BOOL GT64_IsAddrSpaceActive(GT64_HANDLE hGT, GT64_ADDR addrSpace)
  306. {
  307.     return hGT->addrDesc[addrSpace].dwAddr!=0;
  308. }
  309.  
  310. DWORD GT64_ReadReg (GT64_HANDLE hGT, DWORD dwReg)
  311. {
  312.     return GT64_ReadDWord(hGT, GT64_ADDR_REG, dwReg);
  313. }
  314.  
  315. void GT64_WriteReg (GT64_HANDLE hGT, DWORD dwReg, DWORD dwData)
  316. {
  317.     GT64_WriteDWord(hGT, GT64_ADDR_REG, dwReg, dwData);
  318. }
  319.  
  320. DWORD GT64_ReadDWord (GT64_HANDLE hGT, GT64_ADDR addrSpace, DWORD dwOffset)
  321. {
  322.     if (hGT->addrDesc[addrSpace].fIsMemory)
  323.     {
  324.         DWORD dwAddr = hGT->addrDesc[addrSpace].dwAddrDirect + dwOffset;
  325.         DWORD *pDword = (DWORD *) dwAddr;
  326.         return *pDword;
  327.     }
  328.     else
  329.     {
  330.         DWORD dwAddr = hGT->addrDesc[addrSpace].dwAddr + dwOffset;
  331.         WD_TRANSFER trans;
  332.         BZERO(trans);
  333.         trans.cmdTrans = RP_DWORD;
  334.         trans.dwPort = dwAddr;
  335.         WD_Transfer (hGT->hWD, &trans);
  336.         return trans.Data.Dword;
  337.     }
  338. }
  339.  
  340. void GT64_WriteDWord (GT64_HANDLE hGT, GT64_ADDR addrSpace, DWORD dwOffset, DWORD data)
  341. {
  342.     if (hGT->addrDesc[addrSpace].fIsMemory)
  343.     {
  344.         DWORD dwAddr = hGT->addrDesc[addrSpace].dwAddrDirect + dwOffset;
  345.         DWORD *pDword = (DWORD *) dwAddr;
  346.         *pDword = data;
  347.     }
  348.     else
  349.     {
  350.         DWORD dwAddr = hGT->addrDesc[addrSpace].dwAddr + dwOffset;
  351.         WD_TRANSFER trans;
  352.         BZERO(trans);
  353.         trans.cmdTrans = WP_DWORD;
  354.         trans.dwPort = dwAddr;
  355.         trans.Data.Dword = data;
  356.         WD_Transfer (hGT->hWD, &trans);
  357.     }
  358. }
  359.  
  360. void GT64_ReadWriteBlock (GT64_HANDLE hGT, DWORD dwOffset, PVOID buf, 
  361.                     DWORD dwBytes, BOOL fIsRead, GT64_ADDR addrSpace)
  362. {
  363.     DWORD dwAddr = hGT->addrDesc[addrSpace].dwAddr + dwOffset;
  364.     WD_TRANSFER trans;
  365.  
  366.     BZERO(trans);
  367.  
  368.     if (hGT->addrDesc[addrSpace].fIsMemory) 
  369.     {
  370.         if (fIsRead) 
  371.             trans.cmdTrans = RM_SDWORD;
  372.         else 
  373.             trans.cmdTrans = WM_SDWORD;
  374.     }
  375.     else 
  376.     {
  377.         if (fIsRead) 
  378.             trans.cmdTrans = RP_SDWORD;
  379.         else 
  380.             trans.cmdTrans = WP_SDWORD;
  381.     }
  382.     trans.dwPort = dwAddr;
  383.     trans.fAutoinc = TRUE;
  384.     trans.dwBytes = dwBytes;
  385.     trans.dwOptions = 0;
  386.     trans.Data.pBuffer = buf;
  387.     WD_Transfer (hGT->hWD, &trans);
  388. }
  389.  
  390. void GT64_ReadBlock (GT64_HANDLE hGT, DWORD dwOffset, PVOID buf, 
  391.                     DWORD dwBytes, GT64_ADDR addrSpace)
  392. {
  393.     GT64_ReadWriteBlock (hGT, dwOffset, buf, dwBytes, TRUE, addrSpace);
  394. }
  395.  
  396. void GT64_WriteBlock (GT64_HANDLE hGT, DWORD dwOffset, PVOID buf, 
  397.                      DWORD dwBytes, GT64_ADDR addrSpace)
  398. {
  399.     GT64_ReadWriteBlock (hGT, dwOffset, buf, dwBytes, FALSE, addrSpace);
  400. }
  401.  
  402. BOOL GT64_IntIsEnabled (GT64_HANDLE hGT)
  403. {
  404.     if (!hGT->fUseInt) return FALSE;
  405.     if (!hGT->Int.hThread) return FALSE;
  406.     return TRUE;
  407. }
  408.  
  409. VOID GT64_IntHandler (PVOID pData)
  410. {
  411.     GT64_HANDLE hGT = (GT64_HANDLE) pData;
  412.     GT64_INT_RESULT intResult;
  413.     intResult.dwCounter = hGT->Int.Int.dwCounter;
  414.     intResult.dwLost = hGT->Int.Int.dwLost;
  415.     intResult.fStopped = hGT->Int.Int.fStopped;
  416.     intResult.dwStatusReg = hGT->Int.Trans[0].Data.Dword;
  417.     hGT->Int.funcIntHandler(hGT, &intResult);  
  418. }
  419.  
  420. BOOL GT64_IntEnable (GT64_HANDLE hGT, GT64_INT_HANDLER funcIntHandler)
  421. {
  422.     DWORD dwAddr;
  423.  
  424.     if (!hGT->fUseInt) return FALSE;
  425.     // check if interrupt is already enabled
  426.     if (hGT->Int.hThread) return FALSE;
  427.  
  428.     BZERO(hGT->Int.Trans);
  429.     // One transfer commands is issued to CANCEL the source of the interrupt,
  430.     // otherwise, the PC will hang when an interrupt occurs!
  431.     dwAddr = hGT->addrDesc[GT64_ADDR_REG].dwAddr + GT64_INTERRUPT_ACKNOWLEDGE;
  432.     hGT->Int.Trans[0].cmdTrans = hGT->addrDesc[GT64_ADDR_REG].fIsMemory ? RM_DWORD : RP_DWORD;
  433.     hGT->Int.Trans[0].dwPort = dwAddr;
  434.     hGT->Int.Int.dwCmds = 1; 
  435.     hGT->Int.Int.Cmd = hGT->Int.Trans;
  436.     hGT->Int.Int.dwOptions |= INTERRUPT_CMD_COPY;
  437.  
  438.     // this calls WD_IntEnable() and creates an interrupt handler thread
  439.     hGT->Int.funcIntHandler = funcIntHandler;
  440.     if (!InterruptThreadEnable(&hGT->Int.hThread, hGT->hWD, &hGT->Int.Int, GT64_IntHandler, (PVOID) hGT))
  441.         return FALSE;
  442.  
  443.     return TRUE;
  444. }
  445.  
  446. void GT64_IntDisable (GT64_HANDLE hGT)
  447. {
  448.     if (!hGT->fUseInt) return;
  449.     if (!hGT->Int.hThread) return;
  450.  
  451.     // this calls WD_IntDisable()
  452.     InterruptThreadDisable(hGT->Int.hThread);
  453.     hGT->Int.hThread = NULL;
  454. }
  455.  
  456. GT64_DMA_HANDLE GT64_DMAOpen (GT64_HANDLE hGT, DWORD dwLocalAddr, PVOID buf, 
  457.     DWORD dwBytes, BOOL fIsRead, GT64_DAT_TRANS_LIM lim_mode, GT64_DMA_CHANNEL dmaChannel)
  458. {
  459.     DWORD dwChannelShift = dmaChannel*GT64_DMA_CHANNEL_SHIFT;
  460.     BOOL fAutoinc = TRUE;
  461.     GT64_DMA_HANDLE hDma;
  462.     
  463.     if (hGT->gt64Ver == GT64_VERSION_64111) 
  464.     {
  465.         sprintf( GT64_ErrorString, "GT-64111 DMA transfer are not supported\n");
  466.         goto Exit;
  467.     }
  468.     hDma = malloc (sizeof(GT64_DMA_STRUCT));
  469.     if (hDma==NULL)
  470.     {
  471.         sprintf( GT64_ErrorString, "Failed allocating memory for dma handle!\n");
  472.         goto Exit;
  473.     }
  474.     BZERO (*hDma);
  475.     hDma->dmaChannel = dmaChannel;
  476.     hDma->dma.dwBytes = dwBytes;
  477.     hDma->dma.pUserAddr = buf; 
  478.     hDma->dma.dwOptions = 0; 
  479.     WD_DMALock (hGT->hWD, &hDma->dma);
  480.     if (!hDma->dma.hDma) 
  481.     {
  482.         sprintf( GT64_ErrorString, "Failed locking the buffer!\n");
  483.         goto Exit;
  484.     }
  485.     
  486.     hDma->dwDmaControl =  
  487.           ((!fAutoinc && fIsRead)? 0 : BIT3)    // hold source address 
  488.         | ((!fAutoinc && !fIsRead)? 0 : BIT5)   // hold destension address
  489.         | lim_mode       // burst size
  490.         | BIT11          // block transfer mode 
  491.         | BIT12          // to initiate the DMA
  492.         | BIT21 | BIT23 | BIT25; // source, destension, and next record is in PCI_0 Memory space
  493.     if (hDma->dma.dwPages==1)
  494.     {
  495.         hDma->dwDmaControl |= BIT9;  // do not use chain mode
  496.         //dma of one page ==> direct dma
  497.  
  498.         GT64_WriteReg (hGT, GT64_CHANNEL_0_DMA_BYTE_COUNT + dwChannelShift, hDma->dma.Page[0].dwBytes);
  499.         if (fIsRead)
  500.         {
  501.             GT64_WriteReg (hGT, GT64_CHANNEL_0_DMA_SOURCE_ADDRESS + dwChannelShift, dwLocalAddr);
  502.             GT64_WriteReg (hGT, GT64_CHANNEL_0_DMA_DESTINATION_ADDRESS + dwChannelShift
  503.                 , (DWORD) hDma->dma.Page[0].pPhysicalAddr);
  504.         }
  505.         else
  506.         {
  507.             GT64_WriteReg (hGT, GT64_CHANNEL_0_DMA_DESTINATION_ADDRESS + dwChannelShift, dwLocalAddr);
  508.             GT64_WriteReg (hGT, GT64_CHANNEL_0_DMA_SOURCE_ADDRESS + dwChannelShift
  509.                 , (DWORD) hDma->dma.Page[0].pPhysicalAddr);
  510.         }
  511.         GT64_WriteReg (hGT, GT64_CHANNEL_0_NEXT_RECORD_POINTER + dwChannelShift, 0);  //One block
  512.     }
  513.     else
  514.     {
  515.         DWORD dwPageNumber, dwMemoryCopied;
  516.         typedef struct {
  517.             DWORD dwByteCt;
  518.             DWORD dwSrcAdd;
  519.             DWORD dwDestAdd;
  520.             DWORD dwNextRecPtr;
  521.         } DMA_LIST;
  522.         DMA_LIST *pList;
  523.  
  524.         //dma of more then one page ==> chain dma
  525.         hDma->dmaList.dwBytes = hDma->dma.dwPages * sizeof(DMA_LIST);
  526.         hDma->dmaList.pUserAddr = NULL;
  527.         hDma->dmaList.dwOptions = DMA_KERNEL_BUFFER_ALLOC;
  528.         WD_DMALock (hGT->hWD, &hDma->dmaList);
  529.         if (!hDma->dmaList.hDma)
  530.         {
  531.             sprintf (GT64_ErrorString, "Failed locking the chain buffer!\n");
  532.             goto Exit;
  533.         }
  534.  
  535.         //setting chain of dma pages in the memory
  536.         dwMemoryCopied = 0;
  537.         pList = (DMA_LIST *) ((DWORD) hDma->dmaList.pUserAddr);
  538.         for (dwPageNumber=0; dwPageNumber<hDma->dma.dwPages; dwPageNumber++)
  539.         {
  540.             pList[dwPageNumber].dwByteCt = hDma->dma.Page[dwPageNumber].dwBytes;
  541.             if (fIsRead)
  542.             {
  543.                 pList[dwPageNumber].dwSrcAdd = dwLocalAddr + (fAutoinc ? dwMemoryCopied : 0);
  544.                 pList[dwPageNumber].dwDestAdd = (DWORD) hDma->dma.Page[dwPageNumber].pPhysicalAddr;
  545.             }
  546.             else
  547.             {
  548.                 pList[dwPageNumber].dwDestAdd = dwLocalAddr + (fAutoinc ? dwMemoryCopied : 0);
  549.                 pList[dwPageNumber].dwSrcAdd = (DWORD) hDma->dma.Page[dwPageNumber].pPhysicalAddr;
  550.             }
  551.             pList[dwPageNumber].dwNextRecPtr =  
  552.                 ((DWORD) hDma->dmaList.Page[0].pPhysicalAddr + sizeof(DMA_LIST)*(dwPageNumber+1));
  553.             dwMemoryCopied += hDma->dma.Page[dwPageNumber].dwBytes;
  554.         }
  555.         pList[dwPageNumber - 1].dwNextRecPtr = 0 ; // mark end of chain
  556.     
  557.         hDma->dwDmaControl |= BIT10    // interrupt only after finishing all pages
  558.             | BIT13;   // fetching the first record
  559.         // adjusting the first record
  560.         GT64_WriteReg (hGT, GT64_CHANNEL_0_NEXT_RECORD_POINTER + dwChannelShift,
  561.             (DWORD)hDma->dmaList.Page[0].pPhysicalAddr);
  562.     }
  563.     return hDma;
  564.  
  565. Exit:
  566.     if (hDma!=NULL)
  567.         GT64_DMAClose(hGT,hDma);
  568.     return NULL;
  569. }
  570.  
  571. void GT64_DMAClose (GT64_HANDLE hGT, GT64_DMA_HANDLE hDma)
  572. {
  573.     if (hDma->dma.hDma)
  574.         WD_DMAUnlock(hGT->hWD, &hDma->dma);
  575.     if (hDma->dmaList.hDma)
  576.         WD_DMAUnlock(hGT->hWD, &hDma->dmaList);
  577.     free (hDma);
  578. }
  579.  
  580. BOOL GT64_DMAIsDone (GT64_HANDLE hGT, GT64_DMA_HANDLE hDma)
  581. {
  582.     return (GT64_ReadReg (hGT, GT64_CHANNEL_0_CONTROL + hDma->dmaChannel * GT64_DMA_CHANNEL_SHIFT) & BIT14)==BIT14;
  583. }
  584.  
  585. void GT64_DMAStart (GT64_HANDLE hGT, GT64_DMA_HANDLE hDma, BOOL fBlocking)
  586. {
  587.     GT64_WriteReg (hGT, GT64_CHANNEL_0_CONTROL + hDma->dmaChannel * GT64_DMA_CHANNEL_SHIFT, hDma->dwDmaControl);
  588.  
  589.     //Busy wait for GT to finish transfer
  590.     if (fBlocking) 
  591.         while (!GT64_DMAIsDone(hGT, hDma));
  592. }
  593.  
  594. BOOL GT64_DMAReadWriteBlock (GT64_HANDLE hGT, GT64_ADDR addrSpace, DWORD dwLocalAddrOffset, PVOID buf, 
  595.     DWORD dwBytes, BOOL fIsRead, GT64_DAT_TRANS_LIM lim_mode, GT64_DMA_CHANNEL dmaChannel)
  596. {
  597.     DWORD dwLocalAddr = hGT->addrDesc[addrSpace].dwAddrDirect + dwLocalAddrOffset;
  598.     GT64_DMA_HANDLE hDma;
  599.     if (dwBytes==0) 
  600.         return TRUE;
  601.  
  602.     hDma = GT64_DMAOpen(hGT, dwLocalAddr, buf, dwBytes, fIsRead, lim_mode, dmaChannel);
  603.     if (!hDma) 
  604.         return FALSE;
  605.     GT64_DMAStart (hGT, hDma, TRUE);
  606.  
  607.     GT64_DMAClose(hGT, hDma);
  608.     return TRUE;
  609. }
  610.  
  611.